/*******************************************************************************
 * Copyright (c) 2011 Olexandr V. Shaposhnikov.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Olexandr V. Shaposhnikov - initial API and implementation and/or initial documentation
 *******************************************************************************/
package com.funkyroach.use.core.parser.antlr;

import java.io.IOException;
import java.io.InputStream;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.ast.parser.AbstractSourceParser;
import org.eclipse.dltk.compiler.env.IModuleSource;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.utils.TextUtils;

import com.funkyroach.use.core.ast.USModuleDeclaration;

public class USSourceParser extends AbstractSourceParser {

	private boolean typeInformationEnabled = false;

	public boolean isTypeInformationEnabled() {
		return typeInformationEnabled;
	}

	public void setTypeInformationEnabled(boolean typeInformationEnabled) {
		this.typeInformationEnabled = typeInformationEnabled;
	}

	public USModuleDeclaration parse(IModuleSource input,
			IProblemReporter reporter) {
		Assert.isNotNull(input);
		String moduleName = Util.EMPTY_STRING;
		String packageName = Util.EMPTY_STRING;
		if (input.getModelElement() != null) {
			final String fileName = input.getFileName() != null ? input
					.getFileName() : Util.EMPTY_STRING;
			moduleName = USModuleDeclaration.getModuleNameFromFileName(fileName);
			setTypeInformationEnabled(USParserPreferences
					.isTypeInfoEnabled(input.getModelElement()
							.getScriptProject().getProject()));
		}
		char[] source = input.getContentsAsCharArray();
		USModuleDeclaration module = parse(createTokenStream(source),
				new USProblemReporter(TextUtils.createLineTracker(source),
						reporter));
		module.setName(moduleName);
		module.setPackageName(packageName);
		return module;
	}

	public USModuleDeclaration parse(String source, IProblemReporter reporter) {
		Assert.isNotNull(source);
		return parse(createTokenStream(source),
				new USProblemReporter(TextUtils.createLineTracker(source),
						reporter));
	}

	private USModuleDeclaration parse(IUSTokenStream stream,
			USProblemReporter reporter) {
		try {
			stream.setReporter(reporter);
			USParserImpl parser = new USParserImpl(stream, reporter);
			USModuleDeclaration moduleDecl = new USModuleDeclaration();
			parser.us(moduleDecl);
			return moduleDecl;
		} catch (Exception e) {
			if (DLTKCore.DEBUG)
				e.printStackTrace();
			if (reporter != null) {
				// TODO
				// reporter.reportProblem(new USProblem());
			}
			// create empty output
			return new USModuleDeclaration();
		}
	}

	public static IUSTokenStream createTokenStream(char[] source) {
		CharStream charStream = new ANTLRStringStream(source, source.length);
		return new USDynamicTokenStream(new USTokenSource(charStream));
	}

	public static IUSTokenStream createTokenStream(String source) {
		CharStream charStream = new ANTLRStringStream(source);
		return new USDynamicTokenStream(new USTokenSource(charStream));
	}

	/**
	 * @param input
	 * @param encoding
	 * @return
	 * @throws IOException
	 */
	public static IUSTokenStream createTokenStream(InputStream input,
			String encoding) throws IOException {
		CharStream charStream = new ANTLRInputStream(input, encoding);
		return new USDynamicTokenStream(new USTokenSource(charStream));
	}

}
